## Sid Meier's Civilization 4
## Copyright Firaxis Games 2005
##
## CulturalDecay by Bhruic
##

from CvPythonExtensions import *
import CvUtil
import Popup as PyPopup
import DataStorage
import CvEventManager
import PyHelpers
import CvConfigParser

# globals
gc = CyGlobalContext()

PyPlayer = PyHelpers.PyPlayer
PyGame = PyHelpers.PyGame()

data = DataStorage.DataStorage()

# Change this value to false to disable the culture shock effects when a city
# is lost by a civilization.
# Default value is true
g_bEnableCultureShock = true

# Change this value to false to disable the culture decay effects.
# Default value is true 
g_bEnableCultureDecay = true

# Increase or decrease this value to change the amount culture should decay in
# squares outside of an Empire's borders.
# Default value is 0.05
g_iCultureDecayAmount = 0.05

class CvCulturalDecayEventManager:
	def __init__(self, eventManager):

		global g_bEnableCultureShock
		global g_bEnableCultureDecay
		global g_iCultureDecayAmount
		
		config = CvConfigParser.CvConfigParser("ViSa_v3.ini")

		if(config != None):
			g_bEnableCultureShock = config.getboolean("Cultural Influences", "Enable Culture Shock", True)
			g_bEnableCultureDecay = config.getboolean("Cultural Influences", "Enable Culture Decay", True)
			g_iCultureDecayAmount = config.getfloat("Cultural Influences", "Culture Decay Amount", 0.05)
		

		eventManager.addEventHandler("cityBuilt", self.onCityBuilt)
		eventManager.addEventHandler("cityDoTurn", self.onCityDoTurn)

		if(g_bEnableCultureShock):
			eventManager.addEventHandler("cityLost", self.onCityLost)

		if(g_bEnableCultureDecay):
			eventManager.addEventHandler("EndGameTurn", self.onEndGameTurn)

		
		self.Distance = [[0] * 11 for i in range(11)]
		for iX in range(11):
			for iY in range(11):
				if iX in [0, 1] and iY in [0, 1]:
					self.Distance[iX][iY] = 1
				else:
					self.Distance[iX][iY] = int((iX**2 + iY**2)**0.5 + (0.5**2 + 0.5**2)**0.5)
					
										
	def onCityBuilt(self, argsList):
		pCity = argsList[0]
		self.doCultureAdd(pCity, self.getRadius(pCity))
	
	
	def onCityLost(self, argsList):
		pCity = argsList[0]
		self.doCultureShock(pCity, self.getRadius(pCity))
	
		
	def onCityDoTurn(self, argsList):
		pCity = argsList[0]
		self.doCultureAdd(pCity, self.getRadius(pCity))		
	
		
	def onEndGameTurn(self, argsList):
		self.decayCulture()
	
	
	def decayCulture(self):
		pMap = CyMap()
		iTotalPlots = pMap.numPlots()
		
		playerList = PyGame.getCivPlayerList()

		for i in range(iTotalPlots):
			objPlot = pMap.plotByIndex(i)
			
			for objPlayer in playerList:
				iPlayerId = objPlayer.getID()
				iCulture = objPlot.getCulture(iPlayerId)
				iNumCultureCities = objPlot.getNumCultureRangeCities(iPlayerId)
			
				if(iCulture > 0 and iNumCultureCities == 0):
					iCultureDecay = max(((int)(iCulture * g_iCultureDecayAmount)), 1)

					objPlot.changeCulture(iPlayerId, -iCultureDecay, False)


	def doCultureShock(self, pCity, iRadius):
		iCityX = pCity.getX()
		iCityY = pCity.getY()
		iRange = (2 * iRadius) + 1
		iCityId = pCity.getID()
		iCityOwnerId = pCity.getOwner()
		pGame = gc.getGame()
		mapRand = pGame.getMapRand()
		pMap = CyMap()

		for iRangeX in range(iRange):
			for iRangeY in range(iRange):
				iX = iRangeX - iRadius + iCityX
				iY = iRangeY - iRadius + iCityY
				iDistanceX = abs(iRangeX - iRadius)
				iDistanceY = abs(iRangeY - iRadius)

				if (pMap.isPlot(iX, iY) and iRadius >= self.Distance[iDistanceX][iDistanceY]):
					objPlot = pMap.plot(iX, iY)
					iCurrentCulture = data.getSingleVal('CulturalDecay', iCityId, objPlot)
					if (iCurrentCulture > -1):
						iRandNum = mapRand.get(26, "CulturalDecay")
						fRandNum = float(iRandNum) / 100 + 0.5
						iCultureChange = int(iCurrentCulture * fRandNum)
					else:
						iCultureChange = 0

					objPlot.changeCulture(iCityOwnerId, -iCultureChange, False)
					data.setSingleVal('CulturalDecay', iCityId, 0, objPlot)

	
	def doCultureAdd(self, pCity, iRadius):
		iCulture = pCity.getCommerceRate(gc.getInfoTypeForString('COMMERCE_CULTURE'))
		iCityX = pCity.getX()
		iCityY = pCity.getY()
		iRange = (2 * iRadius) + 1
		iCityId = pCity.getID()

		pMap = CyMap()

		for iRangeX in range(iRange):
			for iRangeY in range(iRange):
				iX = iRangeX - iRadius + iCityX
				iY = iRangeY - iRadius + iCityY

				iDistanceX = abs(iRangeX - iRadius)
				iDistanceY = abs(iRangeY - iRadius)
				
				if(pMap.isPlot(iX, iY) and iRadius >= self.Distance[iDistanceX][iDistanceY]):
					objPlot = pMap.plot(iX, iY)
				
					iCultureChange = ((iRadius - self.Distance[iDistanceX][iDistanceY]) * 20 + iCulture + 1)
					iCurrentCulture = data.getSingleVal('CulturalDecay', iCityId, objPlot)
					
					if (iCurrentCulture > -1):
						iCultureChange += iCurrentCulture
					
					data.setSingleVal('CulturalDecay', iCityId, iCultureChange, objPlot)
						
	
	def getRadius(self, pCity):
		iRadius = 0
		pGame = gc.getGame()

		for iCultureLevelInfo in range(gc.getNumCultureLevelInfos()):
			pCultureLevelInfo = gc.getCultureLevelInfo(iCultureLevelInfo)			
			if (pCity.getCulture(pCity.getOwner()) < pCultureLevelInfo.getSpeedThreshold(pGame.getGameSpeedType())):
				iRadius = iCultureLevelInfo - 1
				break
				
		if (iRadius == 0):
			iRadius = iCultureLevelInfo

		return iRadius
		
